package CODEC.Impl;

import CODEC.Encoding;
import Utils.*;
import domain.Message;
import domain.PDU.PDU;
import domain.PDU.Tag.TagType;
import domain.PDU.Type;
import domain.PDU.VariableBindings;

import java.util.HashMap;

/**
 * @Author: ylc
 * @Description:编码模块
 */
public class EncodingImpl implements Encoding {
    Util util = new Util();
    EncodingUtil enutil = new EncodingUtil();
    HashMap<String, Byte> tagCoding = TagType.getTagCoding();

    @Override
    public byte[] getVarCoding(VariableBindings var) {
        String valueType = var.getValueType();
        String value = var.getValue();
        byte[] varCoding = enutil.getOIDCoding(var.getObjectName());
        switch (valueType) {
            case TagType.BOOLEAN:
                varCoding = Util.spliceArr(varCoding, enutil.getBooleanCoding(value));
                break;
            case TagType.INTEGER:
                varCoding = Util.spliceArr(varCoding, enutil.getIntegerCoding(Integer.parseInt(value)));
                break;
            case TagType.OCTET_STRING:
                varCoding = Util.spliceArr(varCoding, enutil.getObjectStringCoding(value));
                break;
            case TagType.NULL:
                varCoding = Util.spliceArr(varCoding, enutil.getNullCoding());
                break;
            case TagType.OBJECT_IDENTIFIER:
                varCoding = Util.spliceArr(varCoding, enutil.getOIDCoding(value));
                break;
            default:
                break;
        }

        byte[] T = new byte[]{tagCoding.get(TagType.SEQUENCE)};

        byte[] L1 = util.exLength(varCoding.length);
        byte[] V1 = util.spliceArr(T, L1, varCoding);

        byte[] allL = util.exLength(V1.length);

        return util.spliceArr(T, allL, V1);
    }

    @Override
    public byte[] getPduCoding(PDU pdu) {
        int pduType = util.getTypeIndex(pdu.getPduType(),Type.PDUTYPE);
        byte[] reqID = enutil.getIntegerCoding(Integer.parseInt(pdu.getRequestId()));
        byte[] errStatus = enutil.getIntegerCoding(util.getTypeIndex(pdu.getErrorStatus(),Type.STATUS));
        byte[] errIndex = enutil.getIntegerCoding(util.getTypeIndex(pdu.getErrorIndex(),Type.STATUS));
        VariableBindings var = pdu.getVariableBindings();

        byte[] pduT = new byte[]{(byte)(160+pduType)};
        byte[] V = util.spliceArr(reqID,errStatus,errIndex);
        byte[] pduV = util.spliceArr(V, getVarCoding(var));
        byte[] pduL = util.exLength(pduV.length);

        return util.spliceArr(pduT, pduL, pduV);
    }

    @Override
    public byte[] getSnmpMessageCoding(Message snmp) {
        byte[] T = new byte[]{tagCoding.get("SEQUENCE")};

        byte[] version = enutil.getIntegerCoding(util.getTypeIndex(snmp.getVersion(), Type.VERSION));
        byte[] community = enutil.getObjectStringCoding(snmp.getCommunity());
        byte[] pdu = getPduCoding(snmp.getPdu());

        byte[] V = util.spliceArr(version,community,pdu);
        byte[] L = util.exLength(V.length);
        return util.spliceArr(T, L, V);
    }


}
